/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.bomt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.bomt.common.enums.BizStepEnum;
import com.comac.ins.bomt.common.enums.TreeNodeTypeEnum;
import com.comac.ins.bomt.domain.Keyword;
import com.comac.ins.bomt.domain.KeywordList;
import com.comac.ins.bomt.domain.vo.BomtTreeNodeVo;
import com.comac.ins.bomt.domain.vo.KeywordListVo;
import com.comac.ins.bomt.domain.vo.KeywordVo;
import com.comac.ins.bomt.mapper.BomtKeywordListDetailMapper;
import com.comac.ins.bomt.mapper.BomtKeywordListInfoMapper;
import com.comac.ins.bomt.service.KeywordListService;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.exception.BizException;
import com.comac.ins.common.core.utils.BizAssertUtil;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.mybatis.helper.BaseEntityHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.comac.ins.bomt.common.constants.CommonConst.AIRCRAFT_MODEL;
import static com.comac.ins.bomt.common.constants.CommonConst.BIND_STEP;

/**
 * 关键词列表服务实现
 *
 * @author zhanghongyi
 * @date 2024/8/6 10:59
 * @description KeywordListServiceImpl
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class KeywordListServiceImpl implements KeywordListService {

    private final BomtKeywordListInfoMapper keywordListInfoMapper;

    private final BomtKeywordListDetailMapper keywordListDetailMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(LoginUser loginUser, String listCode, String listName, BizStepEnum bindStep, String aircraftModel, List<String> keywordList) {
        KeywordList entity = new KeywordList();
        BaseEntityHelper.fillCreateByAndUpdateBy(entity, loginUser);
        entity.setListCode(listCode);
        entity.setListName(listName);
        entity.setBindStep(bindStep.getType());
        entity.setAircraftModel(aircraftModel);
        int insertCnt = keywordListInfoMapper.insert(entity);
        BizAssertUtil.isTrue(insertCnt == 1, "insert wordListInfo record fail");
        add(loginUser, listCode, aircraftModel, new HashSet<>(keywordList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void drop(LoginUser loginUser, String listCode, String aircraftModel) {
        //删除列表的同时删除词
        List<Keyword> wordList = keywordListDetailMapper.selectList(new LambdaQueryWrapper<Keyword>()
            .eq(Keyword::getListCode, listCode).eq(Keyword::getAircraftModel, aircraftModel));
        if (CollectionUtils.isNotEmpty(wordList)) {
            int delWordCnt = keywordListDetailMapper.deleteBatchIds(wordList.stream().map(Keyword::getId).toList());
            BizAssertUtil.isTrue(delWordCnt == wordList.size(), "delete word fail");
        }
        int deleteCnt = keywordListInfoMapper.delete(new LambdaQueryWrapper<KeywordList>()
            .eq(KeywordList::getListCode, listCode).eq(KeywordList::getAircraftModel, aircraftModel));
        BizAssertUtil.isTrue(deleteCnt == 1, "delete wordListInfo record fail");
        log.info("delete list:{},keyWord:{}", listCode, StringUtils.join(",", wordList.stream().map(Keyword::getKeyword).toList()));
    }

    @Override
    public void delete(LoginUser loginUser, String listCode, String aircraftModel, Set<String> keywords) {
        int deleteCnt = keywordListDetailMapper.delete(new LambdaQueryWrapper<Keyword>()
            .eq(Keyword::getListCode, listCode).eq(Keyword::getAircraftModel, aircraftModel).in(Keyword::getKeyword, keywords)
        );
        BizAssertUtil.isTrue(deleteCnt == keywords.size(), "delete word fail");
        log.info("delete list:{},keyWord:{}", listCode, keywords);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(LoginUser loginUser, String listCode, String aircraftModel, Set<String> keywords) {
        Long cnt = keywordListInfoMapper.selectCount(new LambdaQueryWrapper<KeywordList>().eq(KeywordList::getListCode, listCode).eq(KeywordList::getAircraftModel, aircraftModel));
        BizAssertUtil.isTrue(cnt > 0, "wordList not found");
        List<Keyword> wordEntityList = new ArrayList<>();
        for (String keyword : keywords) {
            Keyword entity = new Keyword();
            BaseEntityHelper.fillCreateByAndUpdateBy(entity, loginUser);
            entity.setListCode(listCode);
            entity.setAircraftModel(aircraftModel);
            entity.setKeyword(keyword);
            wordEntityList.add(entity);
        }
        if (CollectionUtils.isNotEmpty(keywords)) {
            try {
                boolean suc = keywordListDetailMapper.insertBatch(wordEntityList);
                BizAssertUtil.isTrue(suc, "insert words fail");
            } catch (DuplicateKeyException duplicateKeyException) {
                throw new BizException("已存在该关键词");
            }
        }

    }

    @Override
    public TableDataInfo<KeywordVo> queryByPage(LoginUser loginUser, String listCode, String aircraftModel, String keyword, PageQuery pageQuery) {

        QueryWrapper<Keyword> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("aircraft_model", aircraftModel);
        queryWrapper.eq("list_code", listCode);
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.like("keyword", keyword);
        }
        Page<KeywordVo> page = keywordListDetailMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }

    @Override
    public List<String> queryByBindType(LoginUser loginUser, BizStepEnum bizStep, String aircraftModel) {

        QueryWrapper<KeywordList> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("aircraft_model", aircraftModel).eq("bind_step", bizStep.getType());
        List<KeywordList> keywordLists = keywordListInfoMapper.selectList(queryWrapper);
        Set<String> keywordSet = new HashSet<>();
        for (KeywordList keywordList : keywordLists) {
            List<Keyword> keywordDetails = keywordListDetailMapper.selectList(new LambdaQueryWrapper<Keyword>().eq(Keyword::getListCode, keywordList.getListCode()).eq(Keyword::getAircraftModel, aircraftModel));
            keywordSet.addAll(keywordDetails.stream().map(Keyword::getKeyword).collect(Collectors.toSet()));
        }
        return keywordSet.stream().toList();
    }

    @Override
    public List<BomtTreeNodeVo> queryAll(LoginUser loginUser) {
        List<KeywordListVo> keywordListVos = keywordListInfoMapper.selectVoList(new QueryWrapper<>());
        List<BomtTreeNodeVo> aircraftTreeNodeVos = new ArrayList<>();
        Map<String, List<KeywordListVo>> groupAircraftLists = keywordListVos.stream().collect(Collectors.groupingBy(KeywordListVo::getAircraftModel));
        //三层树结构：机型-绑定的步骤类型-关键词列表
        for (Map.Entry<String, List<KeywordListVo>> entryAirCraft : groupAircraftLists.entrySet()) {
            BomtTreeNodeVo aircraftTreeNodeVo = new BomtTreeNodeVo();
            aircraftTreeNodeVos.add(aircraftTreeNodeVo);
            aircraftTreeNodeVo.setType(TreeNodeTypeEnum.ROOT.getType());
            aircraftTreeNodeVo.setName(entryAirCraft.getKey());
            aircraftTreeNodeVo.setCode(entryAirCraft.getKey());
            Map<String, List<KeywordListVo>> groupBindStep = entryAirCraft.getValue().stream().collect(Collectors.groupingBy(KeywordListVo::getBindStep));
            for (Map.Entry<String, List<KeywordListVo>> entryBindStep : groupBindStep.entrySet()) {
                BomtTreeNodeVo bindStepTreeNodeVo = new BomtTreeNodeVo();
                aircraftTreeNodeVo.getChildren().add(bindStepTreeNodeVo);
                bindStepTreeNodeVo.setType(TreeNodeTypeEnum.NON_LEAF.getType());
                bindStepTreeNodeVo.setName(BizStepEnum.getByType(entryBindStep.getKey()).getDesc());
                bindStepTreeNodeVo.setCode(entryBindStep.getKey());
                for (KeywordListVo keyWordListVo : entryBindStep.getValue()) {
                    BomtTreeNodeVo keyWordListTreeNodeVo = new BomtTreeNodeVo();
                    bindStepTreeNodeVo.getChildren().add(keyWordListTreeNodeVo);
                    keyWordListTreeNodeVo.setType(TreeNodeTypeEnum.LEAF.getType());
                    keyWordListTreeNodeVo.setCode(keyWordListVo.getListCode());
                    keyWordListTreeNodeVo.setName(keyWordListVo.getListName());
                    keyWordListTreeNodeVo.getExtra().put(AIRCRAFT_MODEL, entryAirCraft.getKey());
                    keyWordListTreeNodeVo.getExtra().put(BIND_STEP, entryBindStep.getKey());
                }
            }
        }
        return aircraftTreeNodeVos;
    }
}
